Analyse des AfD-Wahlerfolgs bei der Bundestagswahl 2021
1 Hintergrund
Die Bundestagswahl ist ein zentrales Ereignis für die Öffentlichkeit in Deutschland. Vor der hohen Relevanz dieses Ereignisses stellt sich die Frage, welche Faktoren die Ursache (oder zumindest Prädiktoren) der Wahlentscheidungen der Bürgerinnen und Bürger sind. Ist beispielsweise die Höhe der Arbeitslosigkeit in einem Wahlkreis ausschlaggebend, dass die eine oder andere Partei gewählt wird?
Die Analyse des Wahlerfolgs der Partei “Alternative für Deutschland” (AfD) ist von besonderem Interesse, da ein Teil ihrer Wählis und Vertretis offenbar die Grundsätze deutscher Politik hinterfragt und vielleicht entgegensteht. So hat das Bundesamt für Verfassungsschutz Teilorganisationen der AfD zum Verdachtsfall für Rechtsextremismus eingestuft.
Die Relevanz der Analyse extremistischer Bewegungen begründet sich mit einem Blick in die deutsche Geschichte: Die (deutsche) Geschichte des 20. Jahrhunderts zeigt, dass rechtsextreme Bewegungen das Potenzial für katastrophale Entwicklungen und schlimmste Verbrechen haben.
Ziel und Gegenstand dieses Workshops ist es nicht, eine Meinung oder ein Urteil über die Einschätzung des Verfassungsschutzes oder der AfD zu treffen. Vielmehr ist vor dem genannten Hintergrund die Analyse, warum bzw. unter welchen Randbedingungen die AfD Stimmen auf sich zieht, von höchstem gesellschaftlichem Interesse.
2 Hinweise
Ziel dieser Analyse ist es, grundlegende Methoden der Datenanalyse für eine angewandte Forschungsfrage bzw. eine Forschungsfrage von allgemeinem Interesse, vorzustellen bzw. einzuüben.
Es handelt sich um eine Analyse mit rein didaktischem Ziel.
Es sind keinerlei politische Aussagen mit dieser Analyse verbunden.
3 Forschungsfragen
Wie groß ist der AfD-Stimmenanteil, aggregiert pro Bundesland und Deutschlandweit? Wie verteilt sich der Stimmenanteil der AfD?
Wie hängt der Wahlerfolg der AfD mit ökonomopolitischen Indikatoren wie Arbeitslosigkeitsquote und Ausländeranteil zusammen?
4 Vorbereitung
4.1 R-Pakete
library(tidyverse)
library(sf) # Geo-Visualisierung
library(rstatix) # Deskriptive Statistiken
library(corrr) # Korrelationsmatrizen
library(gt) # HTML Tabellen
library(rstanarm) # Bayes-Modellierung
library(tictoc)5 Daten aufbereiten
5.1 Ökonomopolitische Strukturdaten
5.1.1 Daten einlesen
Die Strukturdaten sind vom Bundeswahlleiter zu beziehen; über diesen Link kommt man zu den Daten (CSV-Format).
Die Variablennamen sind hier erklärt.
d_str_file <- "data/btw21_Strukturdaten.csv"
d_str <- read_delim(d_str_file,
delim = ";",
escape_double = FALSE,
locale = locale(decimal_mark = ",",
grouping_mark = "."),
trim_ws = TRUE,
skip = 8) Hier sind die Namen der Spalten:
names(d_str)## [1] "Land"
## [2] "Wahlkreis-Nr."
## [3] "Wahlkreis-Name"
## [4] "Gemeinden am 31.12.2019 (Anzahl)"
## [5] "Fläche am 31.12.2019 (km²)"
## [6] "Bevölkerung am 31.12.2019 - Insgesamt (in 1000)"
## [7] "Bevölkerung am 31.12.2019 - Deutsche (in 1000)"
## [8] "Bevölkerung am 31.12.2019 - Ausländer/-innen (%)"
## [9] "Bevölkerungsdichte am 31.12.2019 (EW je km²)"
## [10] "Zu- (+) bzw. Abnahme (-) der Bevölkerung 2019 - Geburtensaldo (je 1000 EW)"
## [11] "Zu- (+) bzw. Abnahme (-) der Bevölkerung 2019 - Wanderungssaldo (je 1000 EW)"
## [12] "Alter von ... bis ... Jahren am 31.12.2019 - unter 18 (%)"
## [13] "Alter von ... bis ... Jahren am 31.12.2019 - 18-24 (%)"
## [14] "Alter von ... bis ... Jahren am 31.12.2019 - 25-34 (%)"
## [15] "Alter von ... bis ... Jahren am 31.12.2019 - 35-59 (%)"
## [16] "Alter von ... bis ... Jahren am 31.12.2019 - 60-74 (%)"
## [17] "Alter von ... bis ... Jahren am 31.12.2019 - 75 und mehr (%)"
## [18] "Bodenfläche nach Art der tatsächlichen Nutzung am 31.12.2019 - Siedlung und Verkehr (%)"
## [19] "Bodenfläche nach Art der tatsächlichen Nutzung am 31.12.2019 - Vegetation und Gewässer (%)"
## [20] "Fertiggestellte Wohnungen 2019 (je 1000 EW)"
## [21] "Bestand an Wohnungen am 31.12.2019 - insgesamt (je 1000 EW)"
## [22] "Wohnfläche am 31.12.2019 (je Wohnung)"
## [23] "Wohnfläche am 31.12.2019 (je EW)"
## [24] "PKW-Bestand am 01.01.2020 - PKW insgesamt (je 1000 EW)"
## [25] "PKW-Bestand am 01.01.2020 - PKW mit Elektro- oder Hybrid-Antrieb (%)"
## [26] "Unternehmensregister 2018 - Unternehmen insgesamt (je 1000 EW)"
## [27] "Unternehmensregister 2018 - Handwerksunternehmen (je 1000 EW)"
## [28] "Schulabgänger/-innen beruflicher Schulen 2019"
## [29] "Schulabgänger/-innen allgemeinbildender Schulen 2019 - insgesamt ohne Externe (je 1000 EW)"
## [30] "Schulabgänger/-innen allgemeinbildender Schulen 2019 - ohne Hauptschulabschluss (%)"
## [31] "Schulabgänger/-innen allgemeinbildender Schulen 2019 - mit Hauptschulabschluss (%)"
## [32] "Schulabgänger/-innen allgemeinbildender Schulen 2019 - mit mittlerem Schulabschluss (%)"
## [33] "Schulabgänger/-innen allgemeinblldender Schulen 2019 - mit allgemeiner und Fachhochschulreife (%)"
## [34] "Kindertagesbetreuung am 01.03.2020 - Betreute Kinder unter 3 Jahre (Betreuungsquote)"
## [35] "Kindertagesbetreuung am 01.03.2020 - Betreute Kinder 3 bis unter 6 Jahre (Betreuungsquote)"
## [36] "Verfügbares Einkommen der privaten Haushalte 2018 (EUR je EW)"
## [37] "Bruttoinlandsprodukt 2018 (EUR je EW)"
## [38] "Sozialversicherungspflichtig Beschäftigte am 30.06.2020 - insgesamt (je 1000 EW)"
## [39] "Sozialversicherungspflichtig Beschäftigte am 30.06.2020 - Land- und Forstwirtschaft, Fischerei (%)"
## [40] "Sozialversicherungspflichtig Beschäftigte am 30.06.2020 - Produzierendes Gewerbe (%)"
## [41] "Sozialversicherungspflichtig Beschäftigte am 30.06.2020 - Handel, Gastgewerbe, Verkehr (%)"
## [42] "Sozialversicherungspflichtig Beschäftigte am 30.06.2020 - Öffentliche und private Dienstleister (%)"
## [43] "Sozialversicherungspflichtig Beschäftigte am 30.06.2020 - Übrige Dienstleister und \"\"ohne Angabe\"\" (%)"
## [44] "Empfänger/-innen von Leistungen nach SGB II Oktober 2020 - insgesamt (je 1000 EW)"
## [45] "Empfänger/-innen von Leistungen nach SGB II Oktober 2020 - nicht erwerbsfähige Hilfebedürftige (%)"
## [46] "Empfänger/-innen von Leistungen nach SGB II Oktober 2020 - Ausländer/-innen (%)"
## [47] "Arbeitslosenquote Februar 2021 - insgesamt"
## [48] "Arbeitslosenquote Februar 2021 - Männer"
## [49] "Arbeitslosenquote Februar 2021 - Frauen"
## [50] "Arbeitslosenquote Februar 2021 - 15 bis 24 Jahre"
## [51] "Arbeitslosenquote Februar 2021 - 55 bis 64 Jahre"
## [52] "Fußnoten"
Es ist vielleicht praktisch, die Spaltennamen für spätere Verwendung in einer Textdatei abzuspeichern:
d_str_names <-
tibble(
var_name = names(d_str),
) %>%
mutate(id = row_number())
write_csv(d_str_names, "objects/d_str_names.csv")5.1.2 Daten aufbereiten
Die Spaltennamen sind etwas unhandlich. Formulieren wir lieber prägnanter:
names(d_str) <- paste0("V",1:ncol(d_str))
d_str2 <-
d_str %>%
select(state = V1,
area_nr = V2,
area_name = V3,
for_prop = V8,
pop_density = V9,
pop_move = V11,
income = V36,
unemp = V47) Sichern wir diese Daten in eine Datei:
write_csv(d_str2, file = "objects/d_str2.csv")5.2 Wahlergebnisse
5.2.1 Daten einlesen
Die Daten sind vom Bundeswahlleiter zu beziehen. Unter diesem Link kommt man direkt zur CSV-Datei.
Eine Erklärung zu den Variablen findet sich hier.
elec_results_file <- "https://www.bundeswahlleiter.de/bundestagswahlen/2021/ergebnisse/opendata/csv/kerg2.csv"
elec_results <- read_delim(elec_results_file,
delim = ";",
escape_double = FALSE,
locale = locale(decimal_mark = ",",
grouping_mark = "."),
trim_ws = TRUE,
skip = 9
) 5.2.2 Daten aufbereiten
Konzentrieren wir uns auf die Zweitstimme, da die bei der BTW die entscheidende ist.
elec_results2 <-
elec_results %>%
select(Gebietsart, Gebietsnummer, Gebietsname, UegGebietsart, UegGebietsnummer, Gruppenart, Gruppenname, Stimme, Prozent, DiffProzentPkt) %>%
filter(Gruppenname == "AfD") %>%
filter(Stimme == 2)elec_results2 <-
elec_results2 %>%
mutate(Gebietsname = ifelse(Gebietsname == "Bundesgebiet",
"Deutschland",
Gebietsname))Sichern wir diese Daten in eine Datei:
write_csv(elec_results2, file = "objects/elec_results2.csv")6 Einfache, univariate Ergebnisse
6.1 Mittelwert des AfD-Wahlerfolgs
6.1.1 … über alle Bundesländer
Achtung! Alle Bundesländer werden gleich gewichtet!
elec_results2 %>%
filter(Gebietsart == "Land") %>%
summarise(AfD_mean = mean(Prozent))## # A tibble: 1 × 1
## AfD_mean
## <dbl>
## 1 12.1
6.1.2 … über Deutschland
elec_results2 %>%
filter(Gebietsart == "Bund") %>%
summarise(AfD_mean = mean(Prozent)) ## # A tibble: 1 × 1
## AfD_mean
## <dbl>
## 1 10.3
6.1.3 … über Wahlkreise
elec_results2 %>%
filter(Gebietsart == "Wahlkreis") %>%
summarise(AfD_mean = mean(Prozent, na.rm = T))## # A tibble: 1 × 1
## AfD_mean
## <dbl>
## 1 10.5
6.2 Wahlerfolg der AfD nach Bundesländern
elec_results2 %>%
filter(Gebietsart == "Land") %>%
select(Gebietsname, Prozent) %>%
mutate(Gebietsname = as.factor(Gebietsname)) %>%
ggplot(aes(x = reorder(Gebietsname, Prozent),
y = Prozent)) +
geom_col() +
coord_flip() +
labs(title = "AfD-Zweitstimmenanteil bei der BTW 21",
caption = "Die Linie zeigt den Mittelwert für ganz Deutschland",
y = "Anteil in Prozent",
x = "Bundesländer") +
geom_hline(yintercept = 10.1) +
annotate("label", x = "Hamburg", y = 10,
label = "Mittelwert",
size = 2) +
geom_text(aes(label = round(Prozent)),
nudge_y = -1,
color = "white",
size = 2)7 Daten zusammenführen (join)
7.1 Erster Versuch
d <-
d_str2 %>%
full_join(elec_results2, by = c("area_name" = "Gebietsname"))Einige Zeilen lassen sich nicht zusammenführen. Schauen wir diese uns näher an:
d %>%
filter(str_detect(area_name, "nsgesamt")) # Ohne "I"!## # A tibble: 17 × 17
## state area_nr area_name for_prop pop_density pop_move income unemp Gebietsart
## <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Schl… 901 Land ins… 8.4 184. 6 22833 6.3 <NA>
## 2 Meck… 913 Land ins… 4.7 69 5 19470 8.7 <NA>
## 3 Hamb… 902 Land ins… 16.5 2446. 2.7 25029 8.1 <NA>
## 4 Nied… 903 Land ins… 9.7 168. 4.4 21988 6.1 <NA>
## 5 Brem… 904 Land ins… 18.5 1624. -1.1 21481 11.6 <NA>
## 6 Bran… 912 Land ins… 5 85 9.1 20475 6.6 <NA>
## 7 Sach… 915 Land ins… 5.1 107. 1.1 19528 8.3 <NA>
## 8 Berl… 911 Land ins… 19.2 4118. 6.3 20972 10.6 <NA>
## 9 Nord… 905 Land ins… 13.6 526. 2.6 22294 7.9 <NA>
## 10 Sach… 914 Land ins… 5.1 221. 3.8 20335 6.6 <NA>
## 11 Hess… 906 Land ins… 16.6 298. 4.5 23943 5.7 <NA>
## 12 Thür… 916 Land ins… 5.2 132. 1.6 19793 6.4 <NA>
## 13 Rhei… 907 Land ins… 11.5 206. 5 23197 5.6 <NA>
## 14 Baye… 909 Land ins… 13.6 186. 4.5 25309 4.2 <NA>
## 15 Bade… 908 Land ins… 15.9 310. 3.4 24892 4.4 <NA>
## 16 Saar… 910 Land ins… 11.4 384. 2.2 20277 7.4 <NA>
## 17 Deut… 999 Insgesamt 12.5 233. 3.9 22899 6.3 <NA>
## # … with 8 more variables: Gebietsnummer <chr>, UegGebietsart <chr>,
## # UegGebietsnummer <chr>, Gruppenart <chr>, Gruppenname <chr>, Stimme <dbl>,
## # Prozent <dbl>, DiffProzentPkt <dbl>
Es sind die Bundesländer, deren area_name “Land insgesamt”, jeweils, lautet.
Diese Felder müssen wir wohl umbenennen.
Bundesländer - plus der Bund als Ganzes - haben eine ID, die mit 9 beginnt, was für sonstige Einheiten nicht der Fall ist:
d_leander <-
d %>%
select(area_nr, area_name, state) %>%
filter(str_detect(area_nr, "^9")) %>%
mutate(area_name = state) %>%
select(-state)Da die Länder auch noch noch eine andere Gebietsnummer haben in der Datei mit den Strukturdaten, fügen wir noch die Gebietsnummer aus elec_results2 hinzu:
d_laender2 <-
d_leander %>%
left_join(elec_results2 %>% select(Gebietsname, Gebietsnummer), by = c("area_name" = "Gebietsname"))Sieht dann so aus:
d_laender2## # A tibble: 17 × 3
## area_nr area_name Gebietsnummer
## <chr> <chr> <chr>
## 1 901 Schleswig-Holstein 01
## 2 913 Mecklenburg-Vorpommern 13
## 3 902 Hamburg 02
## 4 903 Niedersachsen 03
## 5 904 Bremen 04
## 6 912 Brandenburg 12
## 7 915 Sachsen-Anhalt 15
## 8 911 Berlin 11
## 9 905 Nordrhein-Westfalen 05
## 10 914 Sachsen 14
## 11 906 Hessen 06
## 12 916 Thüringen 16
## 13 907 Rheinland-Pfalz 07
## 14 909 Bayern 09
## 15 908 Baden-Württemberg 08
## 16 910 Saarland 10
## 17 999 Deutschland 99
7.2 Zweiter Versuch
Jetzt fügen wir die korrigierten Landesnamen und -nummern zu d_str2 hinzu:
d_str3 <-
d_str2 %>%
left_join(d_laender2, by = "area_nr")area_name.y ist aktuell nur mit Landesnamen (plus Bund) gefüllt. Ergänzen wir also die NAs mit den Namen der Wahlbezirke. Die andere Spalte area_name.x brauchen wir dann nicht mehr.
d_str4 <-
d_str3 %>%
mutate(area_name.y = ifelse(is.na(area_name.y),
area_name.x,
area_name.y)) %>%
select(-area_name.x) %>%
rename(area_name = area_name.y)Das Gleiche machen wir mit area_nr:
d_str5 <-
d_str4 %>%
mutate(area_nr = ifelse(is.na(Gebietsnummer),
area_nr,
Gebietsnummer))d_str5 %>%
slice_head(n=20) ## # A tibble: 20 × 9
## state area_nr for_prop pop_density pop_move income unemp area_name
## <chr> <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
## 1 Schlesw… 001 8.4 137. 9.5 21358 7 Flensburg – Schl…
## 2 Schlesw… 002 7.1 84.6 8.3 24354 6.5 Nordfriesland – …
## 3 Schlesw… 003 6.5 110. 4.6 22292 6.4 Steinburg – Dith…
## 4 Schlesw… 004 5.5 116. 8.6 23410 4.8 Rendsburg-Eckern…
## 5 Schlesw… 005 11.4 1879. -1.8 19718 8.4 Kiel
## 6 Schlesw… 006 8.7 171. 5.1 22081 6.7 Plön – Neumünster
## 7 Schlesw… 007 11.1 476. 8.1 24708 5.9 Pinneberg
## 8 Schlesw… 008 8 240. 5.7 23952 5 Segeberg – Storm…
## 9 Schlesw… 009 5.7 144. 6.8 23411 6.1 Ostholstein – St…
## 10 Schlesw… 010 8.6 237. 8.8 24571 5.1 Herzogtum Lauenb…
## 11 Schlesw… 011 10 580 1.3 20404 8.5 Lübeck
## 12 Schlesw… 01 8.4 184. 6 22833 6.3 Schleswig-Holste…
## 13 Mecklen… 012 6.7 73.9 2.6 19927 8 Schwerin – Ludwi…
## 14 Mecklen… 013 4 63.3 7.5 20014 6.8 Ludwigslust-Parc…
## 15 Mecklen… 014 5.5 278 6 19274 7.9 Rostock – Landkr…
## 16 Mecklen… 015 4.7 84.7 6.7 19231 11 Vorpommern-Rügen…
## 17 Mecklen… 016 3.8 53.8 2.8 18774 9.9 Mecklenburgische…
## 18 Mecklen… 017 3 40 4.2 19679 8.5 Mecklenburgische…
## 19 Mecklen… 13 4.7 69 5 19470 8.7 Mecklenburg-Vorp…
## 20 Hamburg 018 21.8 3044. 2.7 25029 8.1 Hamburg-Mitte
## # … with 1 more variable: Gebietsnummer <chr>
Scheint zu passen.
d <-
d_str5 %>%
left_join(elec_results2, by = c("area_nr" = "Gebietsnummer"))dim(d)## [1] 316 18
316 ist eine gute Zahl:
- 299 Wahlbezirke
- 16 Länder
- 1 Bund
7.3 Check
Prüfen wir, ob es noch fehlende Werte nach dem Join gibt:
d %>%
filter(is.na(Gruppenname), is.na(Prozent)) %>%
select(area_name, area_nr, Prozent) %>%
nrow()## [1] 0
Zählen wir die Anzahl der Wahleinheiten nach Art:
d %>%
group_by(Gebietsart) %>%
count()## # A tibble: 3 × 2
## # Groups: Gebietsart [3]
## Gebietsart n
## <chr> <int>
## 1 Bund 1
## 2 Land 16
## 3 Wahlkreis 299
Das sieht gut aus.
7.4 Geo-Daten
Die Geodaten sind ebenfalls erhältlich beim Bundeswahlleiter.
Die Geodaten zur Visualisierung der Wahlkreise werden im sog. “Shape-Format” (.shp) geliefert.
geo_file <- "data/btw21_geometrie_wahlkreise_shp/Geometrie_Wahlkreise_20DBT.shp"Einlesen:
wahlkreise_shp <- st_read(geo_file)## Reading layer `Geometrie_Wahlkreise_20DBT' from data source
## `/Users/sebastiansaueruser/github-repos/afd-btw21-analyse/data/btw21_geometrie_wahlkreise_shp/Geometrie_Wahlkreise_20DBT.shp'
## using driver `ESRI Shapefile'
## Simple feature collection with 299 features and 4 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 280371.1 ymin: 5235856 xmax: 921120.1 ymax: 6101444
## Projected CRS: ETRS89 / UTM zone 32N
Hilfe zu st_read() findet sich hier oder auf der Dokumentation zum R-Paket sf (simple feature).
Plotten:
wahlkreise_shp %>%
ggplot() +
geom_sf()Der Aufbau des Datensatzes ist aufgeräumt:
glimpse(wahlkreise_shp)## Rows: 299
## Columns: 5
## $ WKR_NR <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14, 15, 16, 17, 18, 1…
## $ WKR_NAME <chr> "Flensburg – Schleswig", "Nordfriesland – Dithmarschen Nord"…
## $ LAND_NR <chr> "01", "01", "01", "01", "01", "01", "01", "01", "01", "01", …
## $ LAND_NAME <chr> "Schleswig-Holstein", "Schleswig-Holstein", "Schleswig-Holst…
## $ geometry <MULTIPOLYGON [m]> MULTIPOLYGON (((545529.8 60..., MULTIPOLYGON ((…
7.5 Geo-Daten joinen
d2 <-
d %>%
mutate(area_nr = as.integer(area_nr)) %>%
full_join(wahlkreise_shp, by = c("area_nr" = "WKR_NR"))8 Geo-Vis
8.1 AfD-Anteil
d2 %>%
ggplot() +
geom_sf(aes(fill = Prozent,
geometry = geometry))Verschönern:
d2 %>%
ggplot() +
geom_sf(aes(fill = Prozent,
geometry = geometry),
color = NA) +
scale_fill_viridis_c() +
theme_void() +
labs(title = "Anteil der Zweitstimmen für die AfD",
subtitle = "Bundestagswahl 2021",
fill = "Anteil AfD-Zweitstimmen") +
theme(legend.position = "bottom")Ein paar Wahlkreise haben entweder nicht erwischt, oder es gibt keine Daten.
8.2 Ausländeranteil
d2 %>%
ggplot() +
geom_sf(aes(fill = for_prop,
geometry = geometry),
color = NA) +
scale_fill_viridis_c() +
theme_void()8.3 Arbeitslosigkeit
d2 %>%
ggplot() +
geom_sf(aes(fill = unemp,
geometry = geometry),
color = NA) +
scale_fill_viridis_c() +
theme_void()8.4 Bevölkerungsdichte
d2 %>%
ggplot() +
geom_sf(aes(fill = pop_density,
geometry = geometry),
color = NA) +
scale_fill_viridis_c() +
theme_void()Oder vielleicht lieber Bevölkerungsdichte in der Log2-Skala?
d2 %>%
ggplot() +
geom_sf(aes(fill = log2(pop_density),
geometry = geometry),
color = NA) +
scale_fill_viridis_c() +
theme_void()So kommen die Unterschiede optisch deutlich besser zum Tragen.
Zur Erinnerung: +1 auf der Log2-Skala entspricht einer Multiplikation mit 2 auf der Rohskala. Die Log2-Skala zählt also “Verdopplungsschritte”.
9 EDA
9.1 Prädiktoren des AfD-Wahlerfolgs
9.1.1 Ausländeranteil
d2 %>%
filter(Gebietsart == "Wahlkreis") %>%
select(Prozent, for_prop) %>%
ggplot() +
aes(x = for_prop, y = Prozent) +
geom_point(alpha = .7) +
geom_smooth()Interessant! Ein einfacher linearer Trend liegt nicht vor. Vielleicht sehen wir eher zwei, unterschiedliche Cluster?
Cluster 1 ist geprägt von hohem Ausländeranteil und Cluster 2 von geringem. In beiden Clustern ist der Zusammenhang negativ. Allerdings ist dieser Zusammenhang deutlich stärker ausgeprägt für Cluster 1.
9.1.2 Ausländeranteil nach Bundesland
Wenn wir diese Analyse aufteilen nach Bundesländern, sehen wir viellicht klarer.
d2 %>%
filter(Gebietsart == "Wahlkreis") %>%
select(Prozent, for_prop, state) %>%
ggplot() +
aes(x = for_prop, y = Prozent, color = state) +
geom_point(alpha = .7) +
geom_smooth(method = "lm") +
facet_wrap(~ state) +
scale_y_continuous(limits = c(0, 40)) +
theme(legend.position = "none")Es scheint sich in jedem Bundesland ein negativer, linearer Zusammenhang zu zeigen. Es sei denn, der AfD-Anteil ist sehr gering, dann wird der Zusammenhang schwach, also eine Bodeneffekt.
9.2 Bivariate Korrelationen
d2 %>%
select(Prozent, for_prop, unemp, income, pop_density) %>%
cor_mat()## # A tibble: 5 × 6
## rowname Prozent for_prop unemp income pop_density
## * <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Prozent 1 -0.58 0.038 -0.44 -0.3
## 2 for_prop -0.58 1 0.23 0.38 0.65
## 3 unemp 0.038 0.23 1 -0.56 0.51
## 4 income -0.44 0.38 -0.56 1 0.046
## 5 pop_density -0.3 0.65 0.51 0.046 1
d2 %>%
select(Prozent, for_prop, unemp, income, pop_density) %>%
cor_mat() %>%
cor_plot()Das Kreuz zeigt wohl eine Korrelation nahe Null an.
Die Korrelationsmatrix im langen Format:
d2 %>%
select(Prozent, for_prop, unemp, income, pop_density) %>%
cor_mat() %>%
cor_gather() %>%
filter(cor != 1) %>%
filter(var1 == "Prozent") %>%
arrange(cor) %>%
gt() %>%
fmt_number(where(is.numeric), decimals = 2)| var1 | var2 | cor | p |
|---|---|---|---|
| Prozent | for_prop | −0.58 | 0.00 |
| Prozent | income | −0.44 | 0.00 |
| Prozent | pop_density | −0.30 | 0.00 |
| Prozent | unemp | 0.04 | 0.50 |
Je mehr Ausländer, oder auch je mehr Einkommen, desto weniger wird AfD gewählt. Die Arbeitslosigkeit steht fast nicht in einem (linearen) Zusammenhang mit dem AfD-Wahlerfolg.
10 Modellierung
10.1 Daten aufbereiten
Alle Prozessorkerne nutzen:
options(mc.cores = parallel::detectCores())Daten aufbereiten:
d3 <-
d2 %>%
mutate(Prozent_z = scale(Prozent),
for_prop_z = scale(for_prop),
unemp_z = scale(unemp)) %>%
select(Prozent_z, state, for_prop_z, unemp_z, Gebietsname) %>%
filter(state != "Deutschland")10.2 Model 1
10.2.1 Modell berechnen
Modell berechnen:
tic()
m1 <-
stan_glm(Prozent_z ~ state + unemp_z + for_prop_z,
data = d3,
refresh = 0
)
toc()## 2.435 sec elapsed
Modellergebnisse:
m1## stan_glm
## family: gaussian [identity]
## formula: Prozent_z ~ state + unemp_z + for_prop_z
## observations: 315
## predictors: 18
## ------
## Median MAD_SD
## (Intercept) 0.3 0.1
## stateBayern -0.2 0.1
## stateBerlin -0.6 0.2
## stateBrandenburg 0.6 0.2
## stateBremen -1.0 0.3
## stateHamburg -1.1 0.2
## stateHessen -0.2 0.1
## stateMecklenburg-Vorpommern 0.3 0.2
## stateNiedersachsen -0.9 0.1
## stateNordrhein-Westfalen -0.9 0.1
## stateRheinland-Pfalz -0.4 0.1
## stateSaarland -0.5 0.2
## stateSachsen 1.7 0.2
## stateSachsen-Anhalt 0.7 0.2
## stateSchleswig-Holstein -1.1 0.2
## stateThüringen 1.6 0.2
## unemp_z 0.2 0.0
## for_prop_z -0.3 0.0
##
## Auxiliary parameter(s):
## Median MAD_SD
## sigma 0.4 0.0
##
## ------
## * For help interpreting the printed output see ?print.stanreg
## * For info on the priors used see ?prior_summary.stanreg
Modellparameter visualisieren:
plot(m1)10.2.2 Modellergebnisse interpretieren
Fast alle Modellparameter werden vom Modell als relevant angesehen - mit Ausnahme des Koeffizienten für Mecklenburg-Vorpommern.
Die stärksten Koeffizienten finden wir für Sachsen und Thüringen. Das sind auch die Länder mit dem höchsten Wahlerfolg für die AfD.